package cn.tedu.mall.order.listener;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.order.mapper.OrderItemMapper;
import cn.tedu.mall.order.mapper.OrderMapper;
import cn.tedu.mall.pojo.order.dto.OrderAddCondition;
import cn.tedu.mall.pojo.order.model.OmsOrder;
import cn.tedu.mall.pojo.order.model.OmsOrderItem;
import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import cn.tedu.mall.pojo.seckill.dto.SeckillOrderItemAddDTO;
import cn.tedu.mall.seckill.service.ISeckillSkuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class OrderAddListenerSeckillAddImpl implements OrderAddListenerExecutorInter, InitializingBean {
    /**
     * 负责处理秒杀新增订单事务逻辑
     * 代码流程,和负责处理购物车新增订单几乎,一模一样
     * @param orderAddCondition
     * @return
     */
    //远程调用秒杀sku减库存方法
    @DubboReference
    private ISeckillSkuService skuService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Override
    public RocketMQLocalTransactionState execut(OrderAddCondition orderAddCondition) {
        //seckillOrderAddDTO,只包含一个订单商品
        //OBJECT先转化
        SeckillOrderAddDTO orderAddDTO=(SeckillOrderAddDTO) orderAddCondition;
        //减库存 远程dubbo skuId quantity
        try{
            // 秒杀订单减库存,只需要传递一个订单商品
            skuService.redusSeckillSkuCount(
                    orderAddDTO.getSeckillOrderItemAddDTO(),orderAddDTO.getSn());
        }catch (CoolSharkServiceException e){
            //减库存失败
            log.error("业务异常:{}",e.getMessage());
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        OmsOrder omsOrder=new OmsOrder();
        //封装数据,先把orderAddDTO有的数据转过来
        BeanUtils.copyProperties(orderAddDTO,omsOrder);
        //业务方还需要将omsOrder中缺少的字段补齐
        replenishOrder(omsOrder);
        try{
            orderMapper.insertOrder(omsOrder);
        }catch (Exception e){
            log.error("业务异常:{}",e.getMessage());
            return RocketMQLocalTransactionState.UNKNOWN;
        }
        //新增订单,还要新增订单商品
        List<OmsOrderItem> omsOrderItemList=new ArrayList<>();
        SeckillOrderItemAddDTO seckillOrderItemAddDTO = orderAddDTO.getSeckillOrderItemAddDTO();
        OmsOrderItem omsOrderItem=new OmsOrderItem();
        //将秒杀中唯一的一个订单商品,转化成写入数据库的omsOrderItem
        BeanUtils.copyProperties(seckillOrderItemAddDTO,omsOrderItem);
        //准备写入数据库的订单商品list,add添加
        omsOrderItemList.add(omsOrderItem);
        try{
            orderItemMapper.insertOrderItems(omsOrderItemList);
        }catch (Exception e){
            log.error("业务异常:{}",e.getMessage());
            return RocketMQLocalTransactionState.UNKNOWN;
        }
        Message<String> message=
                MessageBuilder.withPayload(orderAddDTO.getSn()).build();
        SendResult sendResult = rocketMQTemplate.syncSend(
                "csmall-order-delay-topic", message,5000,3);
        if (sendResult.getSendStatus().toString().equals("SEND_OK")){
            return RocketMQLocalTransactionState.COMMIT;
        }else {
            log.error("延迟消息发送失败,记录日志,手动,人工处理");
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }
    private void replenishOrder(OmsOrder omsOrder){
        //state 订单状态 默认 未支付0        已支付,已发货,待收货,已收货,已关闭1,已取消,已退单
        omsOrder.setState(0);
        //时间字段 创建时间 修改时间 订单新增时间
        LocalDateTime now=LocalDateTime.now();
        omsOrder.setGmtOrder(now);
        omsOrder.setGmtModified(now);
        omsOrder.setGmtCreate(now);
        //UNDO 添加加钱,并且追加校验规则
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        OrderAddListenerRegister.registe
                (SeckillOrderAddDTO.class.getName(),this);
    }
}
